package brokerServer

import (
	"broker/interface/iserver"
	"broker/struct/common"
	"broker/struct/connection"
	"broker/struct/model"
	"broker/struct/router"
	"broker/utils"
	"broker/utils/logger"
	"fmt"
	"net"
)

type Server struct {

	//服务器名称
	Name string
	//服务器绑定的ip版本
	IPVersion string
	//服务器监听的ip
	IP string
	//服务器监听端口
	Port int

	//路由表
	routers iserver.IRouterTable

	//服务器路由及消息队列管理
	MsgHandle iserver.IMsgHandle
	//连接管理器
	ConnManager iserver.IConnManager

	//订阅主题管理器
	TopicManager iserver.ITopicManager

	/*连接的hook方法*/
	OnConnStart func(connection iserver.IConnection)
	OnConnStop  func(connection iserver.IConnection)
	OnPublish func(connection iserver.IConnection,message model.PublishMessage)
}

func (s *Server) Start() {
	//fmt.Println("[Server] ",utils.Conf)
	logger.Info.Printf("[Server] %s Version %s Listenner at IP :%s,net IP:%s, Port %d,is starting\n", s.Name, utils.GetConfig().Version, s.IP, utils.GetIntranetIp(), s.Port)

	go func() {
		if utils.GetConfig().WorkerPool {
			//开启消息队列及Worker工作池
			s.MsgHandle.StartWorkPool()
		}

		//1.获取一个TCP的Addr
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			logger.Error.Println("[Server] resolve tcp addr error:", err)
			return
		}

		//2.监听服务器的地址
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			logger.Error.Println("[Server] listen ", s.IPVersion, "err ", err)
			return
		}
		logger.Info.Printf("[Server] start  %s successful ,Listening🧐🧐🧐...\n", s.Name)



		//3.阻塞等待客户端连接，处理客户端业务（读写）
		for {

			conn, err := listener.AcceptTCP()
			if err != nil {
				logger.Error.Println("[Server] Accept err", err)
				continue
			}

			//设置最大连接数的判断
			if s.ConnManager.GetLen() >= utils.GetConfig().MaxConn {
				//TODO 传给客户端一个超出最大连接数的错误包
				logger.Error.Println("[Server] Maximum number of connections exceeded")
				conn.Close()
				continue

			}
			common.ConnIDLock.Lock()
			dealConn := connection.NewConnection(s, conn, common.ConnID, s.MsgHandle)
			common.ConnID++
			common.ConnIDLock.Unlock()
			go dealConn.Start()
		}
	}()

}

// Stop 关闭服务器
func (s *Server) Stop() {

	//TODO 将服务器的资源，状态，已开辟的连接信息消除
	//清除所有连接
	s.ConnManager.ClearAll()
}

func (s *Server) Serve() {
	s.Start()

	// TODO 做一些启动服务器之后的额外业务
	//阻塞状态
	select {}
}

func (s *Server) GetRouters() iserver.IRouterTable {
	return s.routers
}

func (s *Server) GetConnManager() iserver.IConnManager {
	return s.ConnManager
}
func (s *Server) GetTopicManager() iserver.ITopicManager {
	return s.TopicManager
}

func NewServer() iserver.IServer {
	s := &Server{
		Name:         utils.GetConfig().Name,
		IPVersion:    utils.GetConfig().IPVersion,
		IP:           utils.GetConfig().Host,
		Port:         utils.GetConfig().Port,
		routers:      router.NewRouterTable(),
		MsgHandle:    connection.NewMsgHandle(),
		ConnManager:  connection.NewConnManager(),
		TopicManager: connection.NewTopicManager(),
	}
	return s
}

// SetOnConnStart /*连接Hook*/
//注册连接启动Hook方法
func (s *Server) SetOnConnStart(onConnStart func(connection iserver.IConnection)) {
	s.OnConnStart = onConnStart
}

// SetOnConnStop 注册连接关闭的Hook方法
func (s *Server) SetOnConnStop(onConnStop func(connection iserver.IConnection)) {
	s.OnConnStop = onConnStop
}

// SetOnPublish 注册连接关闭的Hook方法
func (s *Server) SetOnPublish(onPublish func(connection iserver.IConnection,message model.PublishMessage)) {
	s.OnPublish = onPublish
}

// CallOnConnStart 调用连接启动的Hook方法
func (s *Server) CallOnConnStart(connection iserver.IConnection) {
	if s.OnConnStart != nil {
		s.OnConnStart(connection)
	}

}

// CallOnConnStop 调用连接关闭的Hook方法
func (s *Server) CallOnConnStop(connection iserver.IConnection) {
	if s.OnConnStop != nil {
		s.OnConnStop(connection)
	}

}
// CallOnPublish 调用连接关闭的Hook方法
func (s *Server) CallOnPublish(connection iserver.IConnection,message model.PublishMessage) {
	if s.OnPublish != nil {
		s.OnPublish(connection,message)
	}
}
